package co.fitstart.weapp.api.service.impl;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.demo2do.core.entity.exception.BusinessException;
import com.demo2do.core.persistence.GenericDaoSupport;
import com.demo2do.core.persistence.annotation.Dao;
import co.fitstart.entity.course.schedule.CourseSchedule;
import co.fitstart.entity.course.schedule.ScheduleStatus;
import co.fitstart.entity.course.schedule.StudentSigninRecord;
import co.fitstart.entity.course.schedule.TargetData;
import co.fitstart.entity.courseware.exercise.ExerciseContent;
import co.fitstart.entity.courseware.exercise.PlannedSchedule;
import co.fitstart.entity.user.StudentTargetData;
import co.fitstart.entity.user.inbody.InbodyRecord;
import co.fitstart.entity.utils.DateUtils;
import co.fitstart.weapp.api.dao.BwhRecordDao;
import co.fitstart.weapp.api.dao.CourseScheduleDao;
import co.fitstart.weapp.api.dao.CoursewareDao;
import co.fitstart.weapp.api.dao.InbodyDao;
import co.fitstart.weapp.api.dao.SigninDao;
import co.fitstart.weapp.api.dao.StudentTargetDao;
import co.fitstart.weapp.api.service.CourseSigninService;

/**
 * 
 * @author haiyan_xiao
 *
 */
@Service("courseSiginService")
public class CourseSigninServiceImpl implements CourseSigninService {

    @Dao
    private CourseScheduleDao courseScheduleDao;

    @Dao
    private CoursewareDao coursewareDao;

    @Dao
    private StudentTargetDao studentTargetDao;

    @Dao
    private InbodyDao inbodyDao;
    
    @Dao
    private SigninDao signinDao;

    @Autowired
    private GenericDaoSupport genericDaoSupport;

    @Dao
    private BwhRecordDao bwhRecordDao;
    
    private Logger logger = LoggerFactory.getLogger(CourseSigninServiceImpl.class);

    /*
     * (non-Javadoc)
     * @see co.fitstart.weapp.api.service.CourseSigninService#loadSigninRecord(co.fitstart.entity.course.schedule.CourseSchedule)
     */
    public StudentSigninRecord loadSigninRecord(CourseSchedule courseSchedule) {
        return signinDao.loadSigninRecord(courseSchedule);
    }

    /*
     * (non-Javadoc)
     * @see co.fitstart.weapp.api.service.CourseSigninService#sigin(co.fitstart.entity.course.schedule.CourseSchedule, java.lang.String)
     */
    public void sigin(CourseSchedule courseSchedule, String message) {
        if(courseSchedule.getScheduleStatus().isFinish()) {
            throw new BusinessException("此课时已签到，请勿重复签到");
        } else if(courseSchedule.getScheduleStatus().isSchedule() || courseSchedule.getScheduleStatus().isExpiry()) {
            throw new BusinessException("课时状态有误，不可签到");
        }
        
        if(!courseSchedule.couldSignin()) {
            throw new BusinessException("签到时间已过");
        }
        
        //累计上课课时
        int duration = courseScheduleDao.count(courseSchedule.getStudent(), ScheduleStatus.FINISH) + 1;
        
        //训练内容
        String training = null;
        int session = coursewareDao.count(courseSchedule.getCourseRound(), Arrays.asList(new ScheduleStatus[]{ScheduleStatus.READY, ScheduleStatus.FINISH, ScheduleStatus.EXPIRY}), courseSchedule.getOccurDate(), courseSchedule.getOccurHour());
        List<PlannedSchedule> plannedSchedules = coursewareDao.listPlannedSchedule(courseSchedule.getCourseRound(), session - 1, 1);
        if(!plannedSchedules.isEmpty() && !plannedSchedules.get(0).getContentList().isEmpty()) {
            StringBuffer buffer = new StringBuffer();
            
            for(ExerciseContent content : plannedSchedules.get(0).getContentList()) {
                buffer.append(content.getDescription() + ",");
            }
            
            training = buffer.substring(0, buffer.length() - 1);
        }
        
        //入营时间
        Date firstDate = courseSchedule.getCourseRound().getEffectiveStart();
        //上次测试时间
        Date latestDate = null;
        //体脂目标
        String bfrTarget = null;
        //体脂目标完成率
        Integer bfrCompletionRate = 0;
        //体重目标
        String weightTarget = null;
        //体重目标完成率
        Integer weightCompletionRate = 0;
        //目标
        String target = null;
        
        TargetData targetData = studentTargetDao.load();
        //所有学员累计数据
        BigDecimal totalReduce = (targetData == null || targetData.getBodyFitReducing() == null) ? new BigDecimal(0) : targetData.getBodyFitReducing();
        //个人贡献值
        BigDecimal personalReduce = new BigDecimal(0);
        
        StudentTargetData studentTarget = studentTargetDao.load(courseSchedule.getCourseRound());
        if(studentTarget != null && studentTarget.getTargetType().isDigital()) {
            if(studentTarget.getTargetType().isBodyFatRateReducing()) {
                bfrTarget = "减脂" + studentTarget.getBfrChange() + "%";
                
                if(studentTarget.getWeightChange() != null && studentTarget.getWeightChange() > 0) {
                    weightTarget = "减重" + studentTarget.getWeightChange() + "KG";
                }
            } else if(studentTarget.getTargetType().isWeightLosing()) {
                weightTarget = "减重" + studentTarget.getWeightChange() + "KG";
            } else {
                bfrTarget = "减脂" + studentTarget.getBfrChange() + "%";
                
                weightTarget = "增重" + studentTarget.getWeightChange() + "KG";
            }
            
            Date firstScheduleDate = courseScheduleDao.getFirstScheduleDate(courseSchedule.getCourseRound(), ScheduleStatus.FINISH);
            
            if(firstScheduleDate != null) {
                List<InbodyRecord> inbodyRecords = inbodyDao.list(courseSchedule.getStudent().getUser(), DateUtils.parseDate(DateFormatUtils.format(firstScheduleDate, "yyyy-MM-dd") + " 00:00:00", "yyyy-MM-dd HH:mm:ss"), new Date());
                
                if(inbodyRecords.size() > 1) {
                    InbodyRecord firstInbodyRecord = inbodyRecords.get(0);
                    InbodyRecord latestInbodyRecord = inbodyRecords.get(inbodyRecords.size() - 1);
                    
                    latestDate = latestInbodyRecord.getRecordTimeDate();
                    
                    if(studentTarget.getTargetType().isWeightLosing()) {
                        if((firstInbodyRecord.getWeight() - latestInbodyRecord.getWeight()) * 100 > studentTarget.getWeightChange()) {
                            weightCompletionRate = 100;
                        } else if(firstInbodyRecord.getWeight() > latestInbodyRecord.getWeight()) {
                            weightCompletionRate = (int)((firstInbodyRecord.getWeight() - latestInbodyRecord.getWeight()) * 100 / studentTarget.getWeightChange());
                        }
                    } else if(studentTarget.getTargetType().isBodyFatRateReducing()) {
                        if((firstInbodyRecord.getBfr() - latestInbodyRecord.getBfr()) * 100 > studentTarget.getBfrChange()) {
                            bfrCompletionRate = 100;
                        } else if(firstInbodyRecord.getBfr() > latestInbodyRecord.getBfr()) {
                            bfrCompletionRate = (int)((firstInbodyRecord.getBfr() - latestInbodyRecord.getBfr()) * 10000 / studentTarget.getBfrChange());
                        }
                        
                        if(studentTarget.getWeightChange() != null && studentTarget.getWeightChange() > 0) {
                            if((firstInbodyRecord.getWeight() - latestInbodyRecord.getWeight()) * 100 > studentTarget.getWeightChange()) {
                                weightCompletionRate = 100;
                            } else if(firstInbodyRecord.getWeight() > latestInbodyRecord.getWeight()) {
                                weightCompletionRate = (int)((firstInbodyRecord.getWeight() - latestInbodyRecord.getWeight()) * 100 / studentTarget.getWeightChange());
                            }
                        }
                    } else if(studentTarget.getTargetType().isMuscleBuilding()) {
                        if((firstInbodyRecord.getBfr() - latestInbodyRecord.getBfr()) * 100 > studentTarget.getBfrChange()) {
                            bfrCompletionRate = 100;
                        } else if(firstInbodyRecord.getBfr() > latestInbodyRecord.getBfr()) {
                            bfrCompletionRate = (int)((firstInbodyRecord.getBfr() - latestInbodyRecord.getBfr()) * 10000 / studentTarget.getBfrChange());
                        }
                        
                        if((latestInbodyRecord.getWeight() - firstInbodyRecord.getWeight()) * 100 > studentTarget.getWeightChange()) {
                            weightCompletionRate = 100;
                        } else if(latestInbodyRecord.getWeight() > firstInbodyRecord.getWeight()) {
                            weightCompletionRate = (int)((latestInbodyRecord.getWeight() - firstInbodyRecord.getWeight()) * 100 / studentTarget.getWeightChange());
                        }
                    }
                }
            }
        } else if (studentTarget != null && !studentTarget.getTargetType().isDigital()) {
            target = studentTarget.getTargetType().getDescription();
        }
        
        List<InbodyRecord> inbodyRecords = inbodyDao.list(courseSchedule.getStudent().getUser());
        
        if(inbodyRecords.size() > 1) {
            InbodyRecord firstInbodyRecord = inbodyRecords.get(0);
            InbodyRecord latestInbodyRecord = inbodyRecords.get(inbodyRecords.size() - 1);
            
//            if(studentTarget.getTargetType().isWeightLosing()) {
//                personalReduce = new BigDecimal(firstInbodyRecord.getWeight() - latestInbodyRecord.getWeight());
//            } else if(studentTarget.getTargetType().isBodyFatRateReducing()) {
//                personalReduce = new BigDecimal(firstInbodyRecord.getBfr() - latestInbodyRecord.getBfr());
//            } else if(studentTarget.getTargetType().isMuscleBuilding()) {
//                List<BwhRecord> bwhRecords = bwhRecordDao.list(courseSchedule.getStudent().getUser());
//                
//                if(bwhRecords.size() > 1) {
//                    personalReduce = new BigDecimal(bwhRecords.get(bwhRecords.size() - 1).getBust() - bwhRecords.get(1).getBust());
//                }
//            }
            personalReduce = new BigDecimal((firstInbodyRecord.getBf() > latestInbodyRecord.getBf()) ? (firstInbodyRecord.getBf() - latestInbodyRecord.getBf()) : 0);
        }
        
        int finishHour = courseSchedule.getCourseRound().getFinished() + 1;
        Double avgGrade = courseScheduleDao.getAvgGrade(courseSchedule.getCourseRound(), ScheduleStatus.FINISH);
        int currentRank = 1;
        
        if(courseSchedule.getCourseType().isIndividual()) {
            if(finishHour * 10 % courseSchedule.getCourseRound().getCourseAmount() == 0) {
                currentRank = finishHour * 10 / courseSchedule.getCourseRound().getCourseAmount();
            } else {
                currentRank = finishHour * 10 / courseSchedule.getCourseRound().getCourseAmount() + 1;
            }
        } else if(courseSchedule.getCourseType().isYear()) {
            if(courseSchedule.getCourseRound().getEffectiveStart() != null && courseSchedule.getCourseRound().getEffectiveEnd() != null) {
                long courseRoundTime = courseSchedule.getCourseRound().getEffectiveEnd().getTime() - courseSchedule.getCourseRound().getEffectiveStart().getTime();
                long usedTime = new Date().getTime() - courseSchedule.getCourseRound().getEffectiveStart().getTime();
                
                if(courseRoundTime > 0 && usedTime > 0) {
                    if(usedTime * 10 % courseRoundTime == 0) {
                        currentRank = (int)(usedTime * 10/ courseRoundTime);
                    } else {
                        currentRank = (int)(usedTime * 10/ courseRoundTime) + 1;
                    }
                }
            }
        }
        
        currentRank = currentRank > 10 ? 10 : currentRank;
        
        StudentSigninRecord signinRecord = new StudentSigninRecord(courseSchedule, duration, training, firstDate, latestDate, bfrTarget, bfrCompletionRate, weightTarget, weightCompletionRate, target, studentTarget == null ? null : studentTarget.getTargetType(), totalReduce, personalReduce, finishHour, avgGrade == null ? null : avgGrade.intValue(), currentRank, message);
        genericDaoSupport.save(signinRecord);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.weapp.api.service.CourseSigninService#validate(co.fitstart.entity.course.schedule.CourseSchedule, java.lang.String)
     */
    public void validate(CourseSchedule courseSchedule, String message) {
        String[] messages = StringUtils.split(message, "|");
        
        // 判断门店信息是否匹配
        if(courseSchedule.getSite().getId() != Long.parseLong(messages[0])) {
            throw new BusinessException("门店信息不匹配");
        }
        
        // 判断二维码是否失效
        Date signinDate = new Date(Long.valueOf(messages[1]));
        Date currentDate = new Date(System.currentTimeMillis());
        Date qrcodeDate = org.apache.commons.lang3.time.DateUtils.addSeconds(currentDate, -65);
        logger.info("signinDate: " + DateFormatUtils.format(signinDate, "yyyy-MM-dd HH:mm:ss") + ", currentDate: " + DateFormatUtils.format(currentDate, "yyyy-MM-dd HH:mm:ss") + ", qrcodeDate: " + DateFormatUtils.format(qrcodeDate, "yyyy-MM-dd HH:mm:ss"));
        if(signinDate.before(qrcodeDate) || signinDate.after(currentDate)) {
            throw new BusinessException("二维码已失效");
        }
        
        // 判断当前时间是否在签到时间内
        if(currentDate.before(courseSchedule.getSigninStartTime()) || currentDate.after(courseSchedule.getSigninEndTime())) {
            throw new BusinessException("该时间不在签到时间内");
        }
        
    }

}
